package top.rainbowecho.gateway.security.authentication.social;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.social.UserIdSource;
import org.springframework.social.config.annotation.ConnectionFactoryConfigurer;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurerAdapter;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.ConnectionSignUp;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository;
import org.springframework.social.connect.web.ProviderSignInUtils;
import org.springframework.social.security.SpringSocialConfigurer;
import org.springframework.web.servlet.View;
import top.rainbowecho.gateway.mapper.UserConnectionMapper;
import top.rainbowecho.gateway.security.authentication.social.qq.connect.QqConnectionFactory;
import top.rainbowecho.gateway.security.property.SecurityProperties;
import top.rainbowecho.gateway.security.property.SocialProperties;
import top.rainbowecho.gateway.security.support.AuthenticationIdUserIdSource;

import javax.sql.DataSource;

/**
 * 针对所有第三方登录的公共配置
 *
 * @author rainbow
 * @since 2019/12/15 19:11
 */
@Configuration
@EnableSocial
public class SocialConfig extends SocialConfigurerAdapter {
    private DataSource dataSource;

    private ConnectionSignUp connectionSignUp;

    private ObjectMapper objectMapper;

    private UserConnectionMapper userConnectionMapper;

    private AuthenticationSuccessHandler authenticationSuccessHandler;

    private SecurityProperties securityProperties;

    @Autowired
    public void setSecurityProperties(SecurityProperties securityProperties) {
        this.securityProperties = securityProperties;
    }

    @Autowired
    public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler authenticationSuccessHandler) {
        this.authenticationSuccessHandler = authenticationSuccessHandler;
    }

    @Autowired
    public void setUserConnectionMapper(UserConnectionMapper userConnectionMapper) {
        this.userConnectionMapper = userConnectionMapper;
    }

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Autowired
    public void setConnectionSignUp(ConnectionSignUp connectionSignUp) {
        this.connectionSignUp = connectionSignUp;
    }

    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    /**
     * 添加第三方信息，用于匹配url进行拦截
     *
     * @param connectionFactoryConfigurer 第三方配置
     * @param environment 配置环境
     */
    @Override
    public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer, Environment environment) {
        SocialProperties.QqSocialProperties qqSocialProperties = securityProperties.getAuthentication().getSocial().getQq();
        QqConnectionFactory qqConnectionFactory = new QqConnectionFactory(qqSocialProperties.getProviderId(), qqSocialProperties.getAppId(), qqSocialProperties.getAppSecret());

        connectionFactoryConfigurer.addConnectionFactory(qqConnectionFactory);
    }

    @Override
    public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
        JdbcUsersConnectionRepository jdbcUsersConnectionRepository = new JdbcUsersConnectionRepository(this.dataSource, connectionFactoryLocator, Encryptors.noOpText());
        jdbcUsersConnectionRepository.setTablePrefix("tb_");
        // 设置自动注册
        jdbcUsersConnectionRepository.setConnectionSignUp(connectionSignUp);
        return jdbcUsersConnectionRepository;
    }

    @Bean
    public SpringSocialConfigurer socialConfigurer(SecurityProperties securityProperties) {
        String filterUrl = securityProperties.getAuthentication().getSocial().getFilterUrl();
        QqSocialConfigurer qqSocialConfigurer = new QqSocialConfigurer(filterUrl);
        qqSocialConfigurer.setAuthenticationSuccessHandler(this.authenticationSuccessHandler);
        return qqSocialConfigurer;
    }

    @Bean
    public ProviderSignInUtils providerSignInUtils(ConnectionFactoryLocator connectionFactoryLocator) {
        return new ProviderSignInUtils(connectionFactoryLocator, getUsersConnectionRepository(connectionFactoryLocator));
    }

    /**
     * 如何根据第三方信息获取与本地用户对应的userId
     *
     * @return 自定义的实现类
     */
    @Override
    public UserIdSource getUserIdSource() {
        AuthenticationIdUserIdSource userIdSource = new AuthenticationIdUserIdSource();
        userIdSource.setUserConnectionMapper(userConnectionMapper);
        return userIdSource;
    }

    /**
     * QQ的绑定与解绑视图
     *
     * @return 视图
     */
    @Bean({"connect/qqConnected", "connect/qqConnect"})
    public View qqConnectBindingView() {
        SocialConnectView qqBindingView = new SocialConnectView();
        qqBindingView.setObjectMapper(objectMapper);
        return qqBindingView;
    }
}
